package com.li.config;

import com.li.common.ModelName;
import dev.langchain4j.community.model.dashscope.QwenEmbeddingModel;
import dev.langchain4j.data.segment.TextSegment;
import dev.langchain4j.memory.ChatMemory;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.model.chat.StreamingChatModel;
import dev.langchain4j.model.embedding.EmbeddingModel;
import dev.langchain4j.rag.content.retriever.EmbeddingStoreContentRetriever;
import dev.langchain4j.service.*;
import dev.langchain4j.service.memory.ChatMemoryAccess;
import dev.langchain4j.store.embedding.EmbeddingStore;
import dev.langchain4j.store.embedding.qdrant.QdrantEmbeddingStore;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 被@Configuration修饰的类，spring容器中会通过cglib给这个类创建一个代理，
 * 代理会拦截所有被@Bean修饰的方法，默认情况（bean为单例）
 * 下确保这些方法只被调用一次，从而确保这些bean是同一个bean，即单例的。
 */
@Configuration
public class AiConfig {

    //助手 ,定义一个带有chat 方法的接口
    //扩展 ChatMemoryAccess 接口 ,避免内存泄漏
    public interface Assistant extends ChatMemoryAccess {
        //一个以上的参数用 @UserMessage 注解 哪一个是用户的消息
        String chat(@MemoryId String memoryId, @UserMessage String message);

        //流式响应
        TokenStream streamChat(@MemoryId String memoryId ,@UserMessage String message);

    }
    //静态代理对象chat => 对话内容存储 =>聊天记录ChatMemory =>当前对话
    @Bean("assistant")
    public Assistant assistant(ChatModel chatModel, StreamingChatModel streamingChatModel) {
//        ChatMemory chatMemory = MessageWindowChatMemory.withMaxMessages(10);

        return AiServices.builder(Assistant.class) //使用AiService 创建实例
                .chatModel(chatModel)
                .streamingChatModel(streamingChatModel)
                .chatMemoryProvider(memoryId -> MessageWindowChatMemory.builder()
                        .maxMessages(10).id(memoryId)
                .build()).build();
    }
    public interface ToolAssistant extends ChatMemoryAccess {
        //设置系统消息, 这个提示词让大模型明白自己现在是个什么角色
        //current_time 用@V注解传入
        @SystemMessage("""
                您是"guo-hou"铁路集团有限公司的客户聊天支持代理,名为小千义 ,请以友好乐于助人的方式与客户进行对话.
                您正在通过在线聊天与客户互动 ,在与客户沟通的过程中请讲中文.
                "guo-hou"铁路集团有限公司属于公司名 ,不用翻译成中文.
                您可以处理客户退票业务 ,在客户退票时 ,您必须从用户得到两个信息: 1.客户姓名 2.车票订单号.
                今天的日期是 {{current_time}}
                """)
        TokenStream streamChat(@MemoryId String memoryId ,@UserMessage String message,@V("current_time") String currentTime);
    }



    @Bean("embeddingStore")
    public EmbeddingStore<TextSegment> embeddingStore() {
        return QdrantEmbeddingStore.builder()
                .host("192.168.6.100")
                .port(6334)
                .collectionName("testRAG")
                .build();
    }
//    @Bean("ragAssistant") //todo 整合不了id ,改用工厂类
//    public Assistant ragAssistant(ChatModel chatModel, StreamingChatModel streamingChatModel,
//                                  EmbeddingStore<TextSegment> embeddingStore) {
//        EmbeddingModel embeddingModel  = QwenEmbeddingModel.builder()
//                .modelName(ModelName.TEXT_EMBEDDING_V3)
//                .apiKey(System.getenv("TONGYI_KEY"))
//                .build();
//        EmbeddingStoreContentRetriever contentRetriever = EmbeddingStoreContentRetriever.builder()
//                .embeddingStore(embeddingStore)
//                .embeddingModel(embeddingModel)
//                .maxResults(5) //最多返回5个结果
//                .minScore(0.6) //最小匹配得分
//                .build();
//        return AiServices.builder(Assistant.class)
//                .chatModel(chatModel)
//                .streamingChatModel(streamingChatModel)
//                .contentRetriever(contentRetriever)
//                .chatMemoryProvider(memoryId -> MessageWindowChatMemory.builder()
//                        .maxMessages(10).id(memoryId)
//                        .build()).build();
//    }


}
